# Module 'statcache'
#
# Obtient les statistiques d'un fichier, avec cache.
# Des fonctions permettent de vider le cache ou de supprimer de manière
# sélective des éléments.

import posix


# Le cache.
# Les clés sont des chemins d'accès, les valeurs sont celles renvoyées par
# `posix.stat'.
#
cache = {}


# Obtient les statistiques d'un fichier, y compris si celui-ci n'est pas dans
# le cache.
#
def stat(path):
	try:
		return cache[path]
	except RuntimeError:
		pass
	cache[path] = ret = posix.stat(path)
	return ret


# Vide complètement le cache.
# Hack : afin de vider ce qui est une variable globale, on réimporte ce module
#
def reset():
	import statcache
	# On vérifie si on a bien importé le même module que l'actuel
	if cache is not statcache.cache:
		raise 'désolé mais statcache nous fait sa crise d\'identité'
	statcache.cache = {}


# Enlève l'élément spécifié du cache, s'il existe.
#
def forget(path):
	try:
		del cache[path]
	except RuntimeError:
		pass


# Enlève toutes les entrées du cache dont le chemin d'accès commence par le
# préfixe spécifié.
#
def forget_prefix(prefix):
	n = len(prefix)
	for path in cache.keys():
		if path[:n] = prefix:
			del cache[path]


# Enlève du cache toutes les entrées correspondant aux fichiers situés
# directement à l'intérieur du répertoire spécifié (mais pas dans les
# sous-répertoires).
# 
#
def forget_dir(prefix):
	if prefix[-1:] = '/' and prefix <> '/':
		prefix = prefix[:-1]
	forget(prefix)
	if prefix[-1:] <> '/':
		prefix = prefix + '/'
	n = len(prefix)
	for path in cache.keys():
		if path[:n] = prefix:
			rest = path[n:]
			if rest[-1:] = '/': rest = rest[:-1]
			if '/' not in rest:
				del cache[path]


# Enlève toutes les entrées du cache sauf celles dont le chemin d'accès
# commence par le préfixe spécifié. Après un chdir(), on passe généralement
# à cette fonction l'argument '/'.
#
def forget_except_prefix(prefix):
	n = len(prefix)
	for path in cache.keys():
		if path[:n] <> prefix:
			del cache[path]


# Vérifie si l'objet désigné par le chemin d'accès spécifié est un répertoire.
#
def isdir(path):
	try:
		# le mode est st[0]; le type est mode/4096; S_IFDIR vaut 4
		return stat(path)[0] / 4096 = 4
	except RuntimeError:
		return 0
